<script setup lang='ts'>
import {ref, computed, h, CSSProperties, onMounted, onActivated, onDeactivated, onBeforeUnmount, nextTick, watch, unref} from 'vue'
import {ElTableV2, Column, ElCheckbox, RowClassNameGetter, RowEventHandlers, RowEventHandlerParams} from 'element-plus'
import {TableV2FixedDir, ElInput, ElInputNumber, ElSelect, ElOption} from 'element-plus'
import {tableProps, tableEmits, CellRenderProps} from './dTableV2'
import {BaseHeaderData, TextHeaderData, InputHeaderData, InputNumberHeaderData, SeleteHeaderData, OperHeaderData, defaultSelectionW, defaultSortW} from './dTableV2'
import {AlignType} from '@/api/config'

import Operation from '@/components/dTable/components/operation.vue'

//事件
const emits = defineEmits(tableEmits)

const props = defineProps(tableProps)

//起始index
const baseIndex = computed(() => {
  return (props.pageSize * (props.currentPage - 1))
})

//获取索引
const getItemIndex = (index:number) => {
  return baseIndex.value + index + 1
}

//获取项目索引 没有
const getRowIndex = (row:any):number|undefined => {
  if (!props.tableData) return undefined
  const key = props.rowKey
  for (let i = 0, l = props.tableData.length; i < l; i++) {
    const item = props.tableData[i]
    if (item[key] === row[key]) {
      return i
    }
  }
  return undefined
}


const headerConfig = computed(() => {
  return props.tableHeaderData
})


//获取输入框对齐方式
const getAlign = (type:AlignType|undefined) => {
  if (type === 'center') {
    return 'd-input-text-center'
  }
  else if (type === 'left') {
    return 'd-input-text-left'
  }
  else if (type === 'right') {
    return 'd-input-text-right'
  } else {
    return 'd-input-text-left'
  }
}

const getClass = (type:AlignType|undefined) => {
  return getAlign(type)
}

//获取固定列的位置
const getFixed = (fixed:undefined|boolean|'left'|'right') => {
  if (fixed === 'left') {
    return TableV2FixedDir.LEFT
  } else if (fixed === 'right') {
    return TableV2FixedDir.RIGHT
  } else {
    return undefined
  }
}


//当前单击选中的
const currentRowIndex = ref<null|number>(null)

//根据传入数据设置选中
const setSeleted = (row:any) => {
  if (!row) {
    currentRowIndex.value = null
    emits('rowClick', null, null)
    return
  }
  const data = props.tableData
  const key = props.rowKey
  for (let i = 0, l = data.length; i < l; i++) {
    if (data[i][key] === row[key]) {
      currentRowIndex.value = i
      emits('rowClick', data[i], i)
      return
    }
  }
  //未找到
  currentRowIndex.value = null
  emits('rowClick', null, null)
}


watch(
  () => props.defaultSeleted,
  (defaultSeleted) => {
    setSeleted(defaultSeleted)
  }
)

const getRowClass:RowClassNameGetter<any> = ({rowIndex}) => {
  let classStr = 'd-common-text-main'
  //斑马纹
  if (props.stripe && rowIndex & 1) {
    classStr += ' tablev2-row-stripe'
  }
  //当前点击行
  if (rowIndex === currentRowIndex.value) {
    classStr += ' tablev2-row-cilcked'
  }
  return classStr
}

//行点击事件点击
const onRowClick = (params:RowEventHandlerParams) => {
  currentRowIndex.value = params.rowIndex
  emits('rowClick', params.rowData, params.rowIndex)
}

//文本
const textCellRenderer = (props:CellRenderProps<any>, item:TextHeaderData) => {
  return h(
    'span',
    {
      class:'el-tooltip tablev2-cell-text d-common-width-full',
      title:props.cellData,
      style:item.styleCall ? item.styleCall(props.rowData) : undefined
    },
    props.cellData
  )
}

//输入框
const inputCellRenderer = (props:CellRenderProps<any>, item:InputHeaderData) => {
  return h(
    ElInput,
    {
      modelValue:props.cellData,
      placeholder:item.placeholder,
      disabled:item.disabled,
      style:item.styleCall ? item.styleCall(props.rowData) : undefined
    }
  )
}

//数字输入框
const inputNumberCellRenderer = (props:CellRenderProps<any>, item:InputNumberHeaderData) => {
  return h(
    ElInputNumber,
    {
      modelValue:props.cellData,
      placeholder:item.placeholder,
      step:item.step,
      max:item.max,
      min:item.min,
      stepStrictly:!item.notStrictly,
      disabled:item.disabled,
      style:item.styleCall ? item.styleCall(props.rowData) : undefined
    }
  )
}

//选择器
const seleteCellRenderer = (props:CellRenderProps<any>, item:SeleteHeaderData) => {
  return h(
    ElSelect,
    {
      modelValue:props.cellData,
      placeholder:item.placeholder,
      multiple:item.multiple,
      filterable:item.filterable,
      disabled:item.disabled,
      style:item.styleCall ? item.styleCall(props.rowData) : undefined
    },
    () => item.seleteData.map((seleteData) => {
      return h(ElOption, {key:seleteData.value + '', label:seleteData.label, value:seleteData.value})
    })
  )
}


//操作按钮
const operCellRenderer = (props:CellRenderProps<any>, item:OperHeaderData) => {
  const showBubble = item.showBubble === undefined ? true : item.showBubble
  const forceShowButton = item.forceShowButton === undefined ? false : item.forceShowButton
  return h(
      Operation as any,
      {
        row:props.rowData,
        col:item,
        showBubble,
        forceShowButton,
        onOpertionClick:(name:string, row:any) => { emits('opertionClick', name, row) },
        style:item.styleCall ? item.styleCall(props.rowData) : undefined
      }
  )
}


//获取多选的数据
const getSelectionRows = (data:Array<any>):Array<any> => {
  return data.filter((item) => {
    return item.$checked
  })
}


//多选列

const selectionFlag = ref(false)
const getSelectionColunm = ():Column<any> => {
  return {
    key:'selection',
    width:defaultSelectionW,
    fixed:true,
    cellRenderer:({rowData, rowIndex}) => {
      const data = props.tableData
      const onChange = (value) => {
        rowData.$checked = value
        const arr = getSelectionRows(data)
        if (arr.length === 0) {
          selectionFlag.value = false
        } else if (arr.length === data.length) {
          selectionFlag.value = true
        }
        emits('multipleSelection', getSelectionRows(data))
      }
      const disabled = props.selectable ? props.selectable(rowData, rowIndex) : undefined
      return h(
        ElCheckbox,
        {modelValue:rowData.$checked, indeterminate:false, disabled, onChange}
      )
    },
    headerCellRenderer:() => {
      const data = props.tableData
      const onChange = (value) => {
        data.map((row) => {
          row.$checked = value
          return row
        })
        selectionFlag.value = value
        emits('multipleSelection', value ? data : [])
      }
      const allSelected = data.every((row) => row.$checked) && data.length > 0
      const containsChecked = data.some((row) => row.$checked)
      return h(
        ElCheckbox,
        {modelValue:selectionFlag.value, disabled:data.length === 0, indeterminate:!allSelected && containsChecked, onChange, defaultMultipleSelection:props.defaultMultipleSelection}
      )
    }
  }
}

const setMultipleSelection = (rows:Array<any>) => {
  props.tableData.map((row) => {
    row.$checked = false
    return row
  })
  rows.map((row) => {
    row.$checked = true
    return row
  })
  emits('multipleSelection', rows)
}

watch(
  () => props.defaultMultipleSelection,
  (defaultMultipleSelection) => {
    setMultipleSelection(defaultMultipleSelection)
  }
)


watch(
  () => props.tableData,
  () => {
    //处理边界情况
    currentRowIndex.value = null
    emits('rowClick', null, null)
    selectionFlag.value = false
    setMultipleSelection([])
  }
)

//下标index
const getIndexColunm = ():Column<any> => {
  return {
    key:'index',
    width:defaultSortW,
    fixed:true,
    cellRenderer:({rowIndex}) => {
      return h('span', getItemIndex(rowIndex))
    },
    headerCellRenderer:() => {
      return h('span', '序号')
    }
  }
}

//自适应模式宽高
const responseH = ref(0)
const responseW = ref(0)

//出去固定列的表格可分配剩余宽度
const surplusW = computed(() => {
  //剩余宽度
  let width = unref(responseW.value)
  props.tableHeaderData?.forEach((item) => {
    width -= item.minWidth === undefined ? item.width : 0
  })
  if (props.showSelection) width -= defaultSelectionW
  if (props.showIndex) width -= defaultSortW
  return width
})

//
const totalMinWidth = computed(() => {
  let width = 0
  props.tableHeaderData?.forEach((item) => {
    if (item.minWidth) width += item.minWidth
  })
  return width
})

//如果是自适应模式,需要计算列的宽度
const getItemWidth = (item:BaseHeaderData) => {
  if (props.autoResponse && item.minWidth && !item.fixed) {
    if (surplusW.value <= 0) {
      return item.width
    } else {
      const computW = surplusW.value * item.minWidth / totalMinWidth.value
      if (computW < item.minWidth) {
        return item.minWidth
      } else {
        return Math.floor(computW * 10) / 10
      }
    }
  } else {
    return item.width
  }
}

//初始化表格列配置
const initColunm = (columns:Array<Column<any>>) => {
  const arr = headerConfig.value
  if (arr) {
    arr.forEach((item) => {
      const align:AlignType = item.align ? item.align : 'left'
      const column:Column = {
        align,
        key:item.prop,
        dataKey:item.prop,
        title:item.label,
        width:getItemWidth(item),
        class:getClass(align),
        fixed:getFixed(item.fixed)
      }
      switch (item.columnType) {
      case 'input':
        column.cellRenderer = (params) => inputCellRenderer(params, item)
        break
      case 'inputNumber':
        column.cellRenderer = (params) => inputNumberCellRenderer(params, item)
        break
      case 'selete':
        column.cellRenderer = (params) => seleteCellRenderer(params, item)
        break
      case 'text':
        column.cellRenderer = (params) => textCellRenderer(params, item)
        break
      case 'oper':
        column.cellRenderer = (params) => operCellRenderer(params, item)
        break
      case 'custom':
        column.cellRenderer = item.cellRenderer
        break
      }
      column.headerCellRenderer = item.headerRenderer
      columns.push(column)
    })
  }
}

const getColunms = computed(() => {
  const columns:Array<Column<any>> = []
  if (props.showSelection) columns.push(getSelectionColunm())
  if (props.showIndex) columns.push(getIndexColunm())
  initColunm(columns)
  return columns
})

  type TableV2Instance=InstanceType<typeof ElTableV2>
const dTableV2Ref = ref<TableV2Instance>()


const wrapperStyle = computed(() => {
  const style:CSSProperties = {}
  if (props.autoResponse) {
    style.height = '100%'
    style.position = 'relative'
  }
  return style
})

const tableStyle = computed(() => {
  const style:CSSProperties = {}
  if (props.autoResponse) {
    style.position = 'absolute'
  }
  return style
})

const wrapperRef = ref<HTMLDivElement>()
//重设表格宽高
const resizeTableWH = () => {
  const wrapper = wrapperRef.value
  if (wrapper) {
    responseH.value = Math.floor(wrapper.offsetHeight)
    responseW.value = Math.floor(wrapper.offsetWidth)
  }
}

//暂不处理从自适应变更到固定模式
const onResizeEvt = ref(false)
const initResizeEvt = () => {
  if (!props.autoResponse || onResizeEvt.value) return
  onResizeEvt.value = true
  nextTick().then(resizeTableWH)
  window.addEventListener('resize', resizeTableWH)
}

const offResizeEvt = () => {
  if (!props.autoResponse || !onResizeEvt.value) return
  onResizeEvt.value  = false
  window.removeEventListener('resize', resizeTableWH)
}

const rowEventHandlers = ref<RowEventHandlers>({onClick:onRowClick})

onMounted(() => {
  initResizeEvt()
  setMultipleSelection(props.defaultMultipleSelection)
  setSeleted(props.defaultSeleted)
})

onBeforeUnmount(() => {
  offResizeEvt()
})

onActivated(() => {
  initResizeEvt()
})

onDeactivated(() => {
  offResizeEvt()
})
</script>

<template>
  <div ref="wrapperRef" :style="wrapperStyle">
    <el-table-v2
      v-if="autoResponse?onResizeEvt:true"
      ref="dTableV2Ref"
      :key="tableRefKey"
      v-loading="showLoading"
      :row-key="rowKey"
      :style="tableStyle"
      header-class="d-common-title-third"
      :row-class="getRowClass"
      :cache="3"
      :fixed="autoResponse"
      :row-height="tableRowHeight"
      :header-height="tableHeadHeight"
      :columns="getColunms"
      :height="autoResponse?responseH:tableHeight"
      :width="autoResponse?responseW:tableWidth"
      :data="tableData"
      :row-event-handlers="rowEventHandlers"
    >
      <template #footer>
        <slot name="table-footer" />
      </template>
    </el-table-v2>
  </div>
</template>

  <style>
   .tablev2-row-stripe{
    background-color: var(--el-fill-color-lighter);
   }
   .tablev2-row-cilcked{
    background-color: var(--el-table-current-row-bg-color) !important;
   }
   .tablev2-cell-text{
    white-space: nowrap;
    overflow: hidden;
    text-overflow:ellipsis;
  }
  </style>